#include "dna.h"
#include "libheader.h"

/*****************************************************************************/
/*                                                                           */
/* Constructor and Destructor                                                */
/*                                                                           */
/*****************************************************************************/
DNA::DNA(const char* name, const char* sequence) {
  this->dnaName=name;
  this->dnaSeq=sequence;
  this->seqLength=strlen(sequence);
  this->dnaSeqR=new char[seqLength+1];
  this->shortRep=new unsigned short[seqLength];
  createShortRep();
  creatReverseComp();
  k_size=0;
  this->kRep=NULL;
}

DNA::~DNA() {
  if(dnaName!=NULL)
    delete [] dnaName;
  if(dnaSeq!=NULL)
    delete [] dnaSeq;
  if(dnaSeqR!=NULL)
    delete [] dnaSeqR;
  if(shortRep!=NULL)  
    delete [] shortRep;
  if(kRep!=NULL)  
    delete [] kRep;
}

/*****************************************************************************/
/*                                                                           */
/* Pub 1 Access Attributes                                                   */
/*                                                                           */
/*****************************************************************************/

//get the name of the dna
const char* DNA::getName() {
  return dnaName;
}
  
//get the DNA Sequence
const char* DNA::getSeq() {
  return dnaSeq;
}

//get the reverse complement DNA Sequence
const char* DNA::getSeqR() {
  return dnaSeqR;
}

//get short representation
const unsigned short* DNA::getShortRep(){
  return shortRep;
}
  
//get sequence length
const int DNA::getSeqLength(){
  return seqLength;
}

//get k-mer size
const int DNA::getKSize(){
  return k_size;
}

//get k-mer representation
const unsigned long* DNA::getkRep(){
  return kRep;
}

/*****************************************************************************/
/*                                                                           */
/* Pub 2 Algorithms                                                          */
/*                                                                           */
/*****************************************************************************/

//create k-mer reprsentation
int DNA::createKRep(int k_len){
  if(k_len>0 && k_len<=32){
    k_size=k_len;
  } else {
    return -1;
  }
  
  if(kRep==NULL){
    kRep=new unsigned long[seqLength];
  }
  
  for(int i=0;i<seqLength-k_size+1;i++){
    unsigned long code1=encode1(&shortRep[i], k_size);
    unsigned long code2=encode2(&shortRep[i], k_size);
    kRep[i]=code1 ^ code2;
  }
  return 0;
}




/*****************************************************************************/
/*                                                                           */
/* Pri 1 Algorithms                                                          */
/*                                                                           */
/*****************************************************************************/

//create integer representation of the DNA sequence
void DNA::createShortRep() {  
  for(int i=0;i<seqLength;i++) {
    switch(dnaSeq[i]){
      case 'A':
        shortRep[i]=0;
        break;
      case 'C':
        shortRep[i]=1;
        break;
      case 'G':
        shortRep[i]=2;
        break;
      case 'T':
        shortRep[i]=3;
        break;
    }
  }
}

void DNA::creatReverseComp() {  
  for(int i=0;i<seqLength;i++) {
    switch(dnaSeq[i]){
      case 'A':
      //case 'a':
        dnaSeqR[seqLength-i-1]='T';
        break;
      case 'C':
      //case 'c':
        dnaSeqR[seqLength-i-1]='G';
        break;
      case 'G':
      //case 'g':
        dnaSeqR[seqLength-i-1]='C';
        break;
      case 'T':
      //case 't':
        dnaSeqR[seqLength-i-1]='A';
        break;
    }
  }
  dnaSeqR[seqLength]=0;
}

//encode DNA into k-mer integer
unsigned long DNA::encode1(const unsigned short* seq, int k_length){
  unsigned long value1=0x0;
  
  for(int i=0;i<k_length;i++){
    value1 = value1 << 2;
    value1 = value1 | (unsigned long)seq[i];
  }
  
  return value1;
}

unsigned long DNA::encode2(const unsigned short* seq, int k_length){
  unsigned long value2=0x0;
  
  for(int i=k_length-1;i>=0;i--){
    value2 = value2 << 2;
    value2 = value2 | (unsigned long)(0x3 - seq[i]);
  }
  
  return value2;
}


/*
int main(){
  char* dnaName=new char[20];
  strcpy(dnaName,"seq name");
  char* dnaSeq=new char[100];
  strcpy(dnaSeq,"ACGTAAAGGGTACCAGTACGATTTGCAT");
  DNA* dna=new DNA(dnaName, dnaSeq);
  dna->createSeqRep(20);
  
  delete[] dnaName;
  delete[] dnaSeq;
}
*/
